﻿using Chaotic.Core.Extension;
using Chaotic.Core.RabbonMenu;
using Chaotic.DataBase.DBAccessLibrary.DBAccessLibrary;
using Chaotic.DataBase.DBAccessLibrary.Model;
using Chaotic.Module.DBTool.Models;
using Chaotic.Module.DBTool.ViewModels;
using Chaotic.Module.DBTool.Views;
using Prism.Events;  
using System.Data;
using System.IO;
using System.Windows.Input;

namespace Chaotic.Module.DBTool;

public class DBRabbionCommandMenu: IDBRabbionCommandMenu
{
    private readonly IDialogService _dialogService;
    private readonly IEventAggregator _eventAggregator;
    public DBRabbionCommandMenu(IDialogService dialogService, IEventAggregator eventAggregator)
    {
        _dialogService = dialogService;
        _eventAggregator = eventAggregator;
        AddDbCommand = new DelegateCommand(() =>
        {
            _dialogService.ShowDialog(nameof(RegistDBDialog), result =>
            {
                ConnectionModel? connectionModel = result.Parameters["result"] as ConnectionModel;
                if (connectionModel != null)
                {
                    DBOperatorFactory.GetOperator.ConnectDB(connectionModel);
                    eventAggregator.SendMessage<DBToolMessage>(new DBToolMessage
                    {
                        Target = nameof(DBTreeContentViewModel),
                        ActionName = "Connection"
                    });
                }
            });
        });

        SqlRunCommand = new DelegateCommand(() => 
        {
            SqlContent sqlContent = null;
            try
            {
                if (SysCache.DBConnection == null)
                {
                    throw new Exception("请先连接一个数据库再进行此操作");
                }
                object documentContent = GetActionDocumentControl();
                if (documentContent is SqlContent content)
                {
                    sqlContent = content; 
                    if (sqlContent.DataContext is SqlContentViewModel viewModel)
                    { 
                        eventAggregator.SendMessage<DBToolMessage>(new DBToolMessage
                        {
                            Target = nameof(DBMasterContent),
                            ActionName = "AddOutPutPane",
                            Data = viewModel.SelectedText
                        });
                    }
                }
            }
            catch(Exception ex)
            {
                eventAggregator.SendLogMessage(ex.Message, true);
            }

            if (sqlContent != null)
            {
                sqlContent.SetFocus();
            }
        }, CanExecuteMethodBySelectText);

        SqlFullSelectCommand = new DelegateCommand(() =>
        {
            try
            {
                object documentContent = GetActionDocumentControl();
                if (documentContent is SqlContent sqlContent)
                {
                    if (sqlContent.DataContext is SqlContentViewModel viewModel)
                        viewModel.SelectAll();
                }
            }
            catch (Exception ex)
            {
                eventAggregator.SendLogMessage(ex.Message, true);
            } 
        }, CanExecuteSqlContentMethodByActive);
        SqlClearCommand = new DelegateCommand(() =>
        {
            try
            {
                object documentContent = GetActionDocumentControl();
                if (documentContent is SqlContent sqlContent)
                {
                    if (sqlContent.DataContext is SqlContentViewModel viewModel)
                        viewModel.ClearText();
                }
            }
            catch (Exception ex)
            {
                eventAggregator.SendLogMessage(ex.Message, true);
            }
        }, CanExecuteSqlContentMethodByActive);

        SqlIncreaseCommand = new DelegateCommand(() =>
        {
            try
            {
                object documentContent = GetActionDocumentControl();
                if (documentContent is SqlContent sqlContent)
                {
                    if (sqlContent.DataContext is SqlContentViewModel viewModel)
                        viewModel.IncreaseText();
                }
            }
            catch (Exception ex)
            {
                eventAggregator.SendLogMessage(ex.Message, true);
            }
        }, CanExecuteMethodBySelectText);
        SqlDecreaseCommand = new DelegateCommand(() =>
        {
            try
            {
                object documentContent = GetActionDocumentControl();
                if (documentContent is SqlContent sqlContent)
                {
                    if (sqlContent.DataContext is SqlContentViewModel viewModel)
                        viewModel.DecreaseText();
                }
            }
            catch (Exception ex)
            {
                eventAggregator.SendLogMessage(ex.Message, true);
            }
        }, CanExecuteMethodBySelectText);
        SqlPasteCommand = new DelegateCommand(() =>
        {
            try
            {
                object documentContent = GetActionDocumentControl();
                if (documentContent is SqlContent sqlContent)
                {
                    if (sqlContent.DataContext is SqlContentViewModel viewModel)
                        viewModel.Paste();
                }
            }
            catch (Exception ex)
            {
                eventAggregator.SendLogMessage(ex.Message, true);
            }
        }, CanExecuteSqlContentMethodByActive);
 
        SqlCutCommand = new DelegateCommand(() =>
        {
            try
            {
                object documentContent = GetActionDocumentControl();
                if (documentContent is SqlContent sqlContent)
                {
                    if (sqlContent.DataContext is SqlContentViewModel viewModel)
                        viewModel.Cut();
                }
            }
            catch (Exception ex)
            {
                eventAggregator.SendLogMessage(ex.Message, true);
            }
        }, CanExecuteMethodBySelectText);
        SqlFindCommand = new DelegateCommand(() =>
        {
            try
            {
                object documentContent = GetActionDocumentControl();
                if (documentContent is SqlContent sqlContent)
                {
                    if (sqlContent.DataContext is SqlContentViewModel viewModel)
                        viewModel.FindOrReplace();
                }
            }
            catch (Exception ex)
            {
                eventAggregator.SendLogMessage(ex.Message, true);
            }
        }, CanExecuteSqlContentMethodByActive);
        SqlUndoCommand = new DelegateCommand(() =>
        {
            try
            {
                object documentContent = GetActionDocumentControl();
                if (documentContent is SqlContent sqlContent)
                {
                    if (sqlContent.DataContext is SqlContentViewModel viewModel)
                        viewModel.Undo();
                }
            }
            catch (Exception ex)
            {
                eventAggregator.SendLogMessage(ex.Message, true);
            }
        }, CanExecuteSqlContentMethodByActive);
        SqlRedoCommand = new DelegateCommand(() =>
        {
            try
            {
                object documentContent = GetActionDocumentControl();
                if (documentContent is SqlContent sqlContent)
                {
                    if (sqlContent.DataContext is SqlContentViewModel viewModel)
                        viewModel.Redo();
                }
            }
            catch (Exception ex)
            {
                eventAggregator.SendLogMessage(ex.Message, true);
            }
        }, CanExecuteSqlContentMethodByActive);

        FileSaveCommand = new DelegateCommand(() =>
        {
            try
            {
                object documentContent = GetActionDocumentControl();
                if (documentContent is SqlContent sqlContent)
                { 
                    if (sqlContent.DataContext is SqlContentViewModel viewModel)
                        viewModel.Save();
                }
                else if(documentContent is TableDefinitionContent tableDefinitionContent)
                {
                    if (tableDefinitionContent.DataContext is TableDefinitionContentViewModel viewModel)
                    {
                        if (viewModel.Save())
                        {
                            eventAggregator.SendLogMessage("保存成功", false);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                eventAggregator.SendLogMessage(ex.Message, true);
            }
        }, CanExecuteContentMethodByActive);
        AddFileCommand = new DelegateCommand(() =>
        {
            eventAggregator.SendMessage<DBToolMessage>(new DBToolMessage
            {
                Target = nameof(DBMasterContent),
                ActionName = "AddSqlDocument",
                Data = new SqlDocumentData()
                {
                    FilePath = string.Empty,
                    IsNewFile = true
                }
            }); 
        });
        FileOpenCommand = new DelegateCommand(() =>
        {
            try
            {
                string directoryPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Document");
                if (!Directory.Exists(directoryPath))
                    Directory.CreateDirectory(directoryPath);
                Telerik.Windows.Controls.RadOpenFileDialog dialog = new Telerik.Windows.Controls.RadOpenFileDialog()
                {
                    InitialDirectory = directoryPath,
                    Filter = "文本文件 (*.txt)|*.txt|SQL 文件 (*.sql)|*.sql",
                    FilterIndex = 5
                };

                if (dialog.ShowDialog() == true)
                {
                    foreach (string filePath in dialog.FileNames)
                    {
                        eventAggregator.SendMessage<DBToolMessage>(new DBToolMessage
                        {
                            Target = nameof(DBMasterContent),
                            ActionName = "AddSqlDocument",
                            Data = new SqlDocumentData()
                            {
                                FilePath = dialog.FileName,
                                IsNewFile = false
                            }
                        });
                    } 
                }
            }
            catch (Exception ex)
            {
                eventAggregator.SendLogMessage(ex.Message, true);
            }
        });

        eventAggregator.ResgiterMessage<DBToolMessage>(message =>
        {
            if (message.Target == nameof(SqlContentViewModel))
            {
                if (message.ActionName == "RunSql" && message.Data is SqlContentMessage msg)
                {
                    object documentContent = GetActionDocumentControl();
                    if (documentContent is SqlContent sqlContent)
                    {
                        if (sqlContent.DataContext is SqlContentViewModel viewModel)
                        {
                            viewModel.InsertSql(msg);
                            if ((msg.Status & SqlControlStatus.Run) == SqlControlStatus.Run)
                            {
                                SqlRunCommand.Execute();
                            }
                        }
                    }
                    else
                    {
                        MessageBoxExtension.Show("请先激活一个文档再进行该操作");
                    }
                }
            }
        }); 
    }

    /// <summary>
    /// 激活时能否执行
    /// </summary>
    /// <returns></returns>
    private bool CanExecuteSqlContentMethodByActive()
    {
        try
        {
            object documentContent = GetActionDocumentControl();
            if (documentContent is SqlContent sqlContent)
            {
                return true;
            }
            return false;
        }
        catch (Exception ex)
        {
            _eventAggregator.SendLogMessage(ex.Message, true);
            return false;
        }
    }
    private bool CanExecuteContentMethodByActive()
    {
        try
        {
            object documentContent = GetActionDocumentControl();
            if (documentContent is SqlContent || documentContent is TableDefinitionContent)
            {
                return true;
            }
            return false;
        }
        catch (Exception ex)
        {
            _eventAggregator.SendLogMessage(ex.Message, true);
            return false;
        }
    }
    private bool CanExecuteMethodBySelectText()
    {
        try
        {
            object documentContent = GetActionDocumentControl();
            if (documentContent is SqlContent sqlContent)
            {
                if (sqlContent.DataContext is SqlContentViewModel viewModel)
                    return !string.IsNullOrEmpty(viewModel.SelectedText);
            }
            return false;
        }
        catch (Exception ex)
        {
            _eventAggregator.SendLogMessage(ex.Message, true);
            return false;
        }
    }

    public void RaiseCanExecuteChangedByActive()
    {
        SqlFullSelectCommand.RaiseCanExecuteChanged();
        SqlClearCommand.RaiseCanExecuteChanged();
        SqlPasteCommand.RaiseCanExecuteChanged();
        SqlFindCommand.RaiseCanExecuteChanged();
        SqlUndoCommand.RaiseCanExecuteChanged();
        SqlRedoCommand.RaiseCanExecuteChanged();
        FileSaveCommand.RaiseCanExecuteChanged();
    }

    public void RaiseCanExecuteChangedBySelectText()
    {
        SqlRunCommand.RaiseCanExecuteChanged();
        SqlIncreaseCommand.RaiseCanExecuteChanged();
        SqlDecreaseCommand.RaiseCanExecuteChanged();
        SqlCutCommand.RaiseCanExecuteChanged(); 
    }

    public Func<object> GetActionDocumentControl { get; set; }

    //新建数据源
    public DelegateCommand AddDbCommand { get; set; }
    //删除数据源
    public DelegateCommand RemoveDbCommand { get; set; }
    //连接
    public DelegateCommand DbConnectCommand { get; set; }
    //断开连接
    public DelegateCommand DbUnConnectCommand { get; set; }
    //打开
    public DelegateCommand FileOpenCommand { get; set; }
    //保存
    public DelegateCommand FileSaveCommand { get; set; }
    //新建文档
    public DelegateCommand AddFileCommand { get; set; }
    //运行
    public DelegateCommand SqlRunCommand { get; set; }
    //粘贴
    public DelegateCommand SqlPasteCommand { get; set; }
    //剪切
    public DelegateCommand SqlCutCommand { get; set; }
    //清空
    public DelegateCommand SqlClearCommand { get; set; }
    //全选
    public DelegateCommand SqlFullSelectCommand { get; set; }
    //注释
    public DelegateCommand SqlIncreaseCommand { get; set; }
    //取消注释
    public DelegateCommand SqlDecreaseCommand { get; set; }
    //查找
    public DelegateCommand SqlFindCommand { get; set; }
 
    //撤销
    public DelegateCommand SqlUndoCommand { get; set; }
    //重做
    public DelegateCommand SqlRedoCommand { get; set; }


    public void InitMenu()
    {
        TabViewModel DbTab = new TabViewModel();
        DbTab.Text = "数据库";
        DbTab.Groups.Add(GetConnectGroup());
        DbTab.Groups.Add(GetSelectGroup());
        DbTab.Groups.Add(GetCutGroup());
        DbTab.Groups.Add(GetFindGroup());
        RabbonMenuManager.Instance.Tabs.Add(DbTab);
    }

    //连接分组
    private GroupModel GetConnectGroup()
    {
        GroupModel group = new GroupModel();
        group.Text = "连接";
        ButtonModel addDbButton = new ButtonModel
        {
            Text = "新建数据源",
            Size = 2, // Large
            LargeImage = GetPath("Menu/add_32x32.png"),
            ClickCommand = AddDbCommand
        };
        group.Buttons.Add(addDbButton);


        ButtonModel removeDbButton = new ButtonModel
        {
            Text = "删除数据源",
            Size = 2, // Large
            LargeImage = GetPath("Menu/close-32x32.png"),
            ClickCommand = RemoveDbCommand
        };
        group.Buttons.Add(removeDbButton);

        ButtonGroupModel cGroup = new ButtonGroupModel()
        {
            VerticalType = System.Windows.VerticalAlignment.Top
        };
        ButtonModel connectButton = new ButtonModel
        {
            Text = "连接",
            Size = 1, // Medium
            LargeImage = GetPath("Tree/btnconnect.png"),
            ClickCommand = DbConnectCommand
        };
        cGroup.Buttons.Add(connectButton);
        ButtonModel unconnectButton = new ButtonModel
        {
            Text = "断开",
            Size = 1, // Medium
            LargeImage = GetPath("Tree/btnunconnect.png"),
            ClickCommand = DbUnConnectCommand
        };
        cGroup.Buttons.Add(unconnectButton);

        group.Buttons.Add(cGroup);

        return group;
    }
    //查询分组
    private GroupModel GetSelectGroup()
    {
        GroupModel group = new GroupModel();
        group.Text = "查询";
        ButtonModel openFileButton = new ButtonModel
        {
            Text = "打开",
            Size = 2, // Large
            LargeImage = GetPath("Menu/open-32x32.png"),
            ClickCommand = FileOpenCommand
        };
        group.Buttons.Add(openFileButton);


        ButtonModel saveFileButton = new ButtonModel
        {
            Text = "保存",
            Size = 2, // Large
            LargeImage = GetPath("Menu/save-32x32.png"),
            ClickCommand = FileSaveCommand
        };
        group.Buttons.Add(saveFileButton);

        ButtonModel addFileButton = new ButtonModel
        {
            Text = "新建文档",
            Size = 2, // Large
            LargeImage = GetPath("Menu/new-32x32.png"),
            ClickCommand = AddFileCommand
        };
        group.Buttons.Add(addFileButton);

        ButtonModel runButton = new ButtonModel
        {
            Text = "运行",
            Size = 2, // Large
            LargeImage = GetPath("Menu/run.png"),
            ClickCommand = SqlRunCommand
        };
        group.Buttons.Add(runButton);

        return group;
    }
    //剪切板分组
    private GroupModel GetCutGroup()
    {
        GroupModel group = new GroupModel();
        group.Text = "剪切板";
        ButtonModel copyButton = new ButtonModel
        {
            Text = "粘贴",
            Size = 2, // Large
            LargeImage = GetPath("Menu/paste-32x32.png"),
            ClickCommand = SqlPasteCommand
        };
        group.Buttons.Add(copyButton);

        ButtonGroupModel cGroup = new ButtonGroupModel()
        {
            VerticalType = System.Windows.VerticalAlignment.Top
        };
        ButtonModel cutButton = new ButtonModel
        {
            Text = "剪切",
            Size = 1, // Medium
            LargeImage = GetPath("Menu/cut-32x32.png"),
            ClickCommand = SqlCutCommand
        };
        cGroup.Buttons.Add(cutButton);

        ButtonModel clearButton = new ButtonModel
        {
            Text = "清空",
            Size = 1, // Medium
            LargeImage = GetPath("Menu/delete_16x16.png"),
            ClickCommand = SqlClearCommand
        };
        cGroup.Buttons.Add(clearButton);

        ButtonModel fullSelectButton = new ButtonModel
        {
            Text = "全选",
            Size = 1, // Medium
            LargeImage = GetPath("Menu/selectall_32x32.png"),
            ClickCommand = SqlFullSelectCommand
        };
        cGroup.Buttons.Add(fullSelectButton);

        ButtonModel increaseButton = new ButtonModel
        {
            Text = "注释",
            Size = 1, // Medium
            LargeImage = GetPath("Menu/indentincrease_16x16.png"),
            ClickCommand = SqlIncreaseCommand
        };
        cGroup.Buttons.Add(increaseButton);

        ButtonModel decreaseButton = new ButtonModel
        {
            Text = "取消注释",
            Size = 1, // Medium
            LargeImage = GetPath("Menu/indentdecrease_16x16.png"),
            ClickCommand = SqlDecreaseCommand
        };
        cGroup.Buttons.Add(decreaseButton);

        group.Buttons.Add(cGroup);
        return group;
    }
    //查找分组
    private GroupModel GetFindGroup()
    {
        GroupModel group = new GroupModel();
        group.Text = "查找";
        ButtonModel findButton = new ButtonModel
        {
            Text = "查找",
            Size = 2, // Large
            LargeImage = GetPath("Menu/find_32x32.png"),
            ClickCommand = SqlFindCommand
        };
        group.Buttons.Add(findButton);


        //ButtonModel replaceButton = new ButtonModel
        //{
        //    Text = "替换",
        //    Size = 2, // Large
        //    LargeImage = GetPath("Menu/replace_32x32.png"),
        //    ClickCommand = SqlReplaceCommand
        //};
        //group.Buttons.Add(replaceButton);

        ButtonModel undoButton = new ButtonModel
        {
            Text = "撤销",
            Size = 2, // Large
            LargeImage = GetPath("Menu/undo-32x32.png"),
            ClickCommand = SqlUndoCommand
        };
        group.Buttons.Add(undoButton);

        ButtonModel redoButton = new ButtonModel
        {
            Text = "重做",
            Size = 2, // Large
            LargeImage = GetPath("Menu/redo-32x32.png"),
            ClickCommand = SqlRedoCommand
        };
        group.Buttons.Add(redoButton);

        return group;
    }


    private const string format = "/Chaotic.Module.DBTool;component/Images/{0}";
    private string GetPath(string fileName)
    {
        string icon = string.Format(format, fileName);

        return icon;
    }
}

public interface IDBRabbionCommandMenu
{
    void InitMenu();

    DelegateCommand DbConnectCommand { get; set; }
    DelegateCommand DbUnConnectCommand { get; set; }
    DelegateCommand RemoveDbCommand { get; set; }
    DelegateCommand SqlRunCommand { get; set; }

    DelegateCommand SqlClearCommand { get; set; }
    DelegateCommand SqlFullSelectCommand { get; set; }
    DelegateCommand SqlIncreaseCommand { get; set; }
    DelegateCommand SqlDecreaseCommand { get; set; }
    DelegateCommand SqlPasteCommand { get; set; }
    DelegateCommand SqlCutCommand { get; set; }
    DelegateCommand SqlFindCommand { get; set; }
    DelegateCommand SqlUndoCommand { get; set; }
    DelegateCommand SqlRedoCommand { get; set; }
    DelegateCommand FileSaveCommand { get; set; }
    DelegateCommand AddFileCommand { get; set; }
    DelegateCommand FileOpenCommand { get; set; }

    Func<object?> GetActionDocumentControl { get; set; }
    void RaiseCanExecuteChangedByActive();
    void RaiseCanExecuteChangedBySelectText();
}